package com.billdowney.qq.robot.plugins;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.billdowney.qq.robot.bean.ConfigBean;
import lombok.extern.slf4j.Slf4j;
import net.mamoe.mirai.contact.MemberPermission;
import net.mamoe.mirai.message.data.At;
import net.mamoe.mirai.message.data.PlainText;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 系统操作机器人
 *
 * @author BillDowney
 * @date 2021/4/4 21:02
 */
@Component
@Slf4j
public class SystemRobotPlugin implements InitializingBean {

    private final String template = "名称：%s；启动：%s\n";
    /**
     * 机器人启动标记
     */
    private static boolean start = true;
    /**
     * 根据群号隔离每个插件的启动
     */
    private final Map<Long, RobotPluginManage> manages = new HashMap<>();
    @Autowired
    private ConfigBean configBean;
    /**
     * root管理员qq列表，拥有最高权限
     */
    private static final Set<Long> ROOT_MANAGE_QQ = new HashSet<>();
    /**
     * 普通管理员qq列表
     */
    private static final Set<Long> NORMAL_MANAGE_QQ = new HashSet<>();
    /**
     * 群白名单
     */
    private static final Set<Long> GROUP_WHITE_LIST = new HashSet<>();
    /**
     * 群管理权限是否有管理机器人的权限
     */
    private static boolean GROUP_ADMIN_PERMISSION = true;

    @Override
    public void afterPropertiesSet() throws Exception {
        ROOT_MANAGE_QQ.addAll(configBean.getRootManageQq());
        GROUP_WHITE_LIST.addAll(configBean.getGroupWhiteList());
    }

    public RobotPluginInfo info() {
        return RobotPluginInfo.create("系统管理插件", true)
                .addDescLn("使用方式(需要配置管理员qq)：")
                .addDescLn("#管理员列表")
                .addDescLn("(root管理员)#添加管理员 {qq号/@群成员}")
                .addDescLn("(root管理员)#删除管理员 {qq号/@群成员}")
                .addDescLn("#开机(root管理员)")
                .addDescLn("#关机(root管理员)")
                .addDescLn("#机器人状态")
                .addDescLn("#插件列表")
                .addDescLn("#开启插件 {插件名称}")
                .addDescLn("#关闭插件 {插件名称}")
                .addDescLn("#插件详情 {插件名称}")
                .addDescLn("(root管理员)#群白名单")
                .addDescLn("(root管理员)#添加群 {群号}")
                .addDescLn("(root管理员)#删除群 {群号}")
                .addDescLn("(root管理员)#开启群管理员权限")
                .addDescLn("(root管理员)#关闭群管理员权限")
                ;
    }

    public void execute(RobotPluginContent content) {
        // 判断当前的群号或者用户qq号，用于后续判断和管理
        if (content.getRobotEventEnum().isGroupMsg()) {
            content.setPluginQqKey(content.getGroupMessageEvent().getGroup().getId());
            // 如果是群消息，则必须在白名单内才执行后续操作
            if (!GROUP_WHITE_LIST.contains(content.getGroupMessageEvent().getGroup().getId())) {
                content.setExecuteNext(false);
                return;
            }
        }
        // 检查是否需要初始化插件管理内容
        this.initPlugin(content.getPluginQqKey());
        // 只能管理员qq才能执行系统管理命令
        if (content.getRobotEventEnum().isMessageEvent()) {
            Long qq = content.getMessageEvent().getSender().getId();
            if (ROOT_MANAGE_QQ.contains(qq) || NORMAL_MANAGE_QQ.contains(qq)) {
                this.command(content);
            } else if (GROUP_ADMIN_PERMISSION && content.getRobotEventEnum().isGroupMsg()) {
                MemberPermission permission = content.getGroupMessageEvent().getSender().getPermission();
                // 群主或者管理员
                if (MemberPermission.ADMINISTRATOR.equals(permission) || MemberPermission.OWNER.equals(permission)) {
                    this.command(content);
                }
            }
        }
    }

    /**
     * 命令执行
     *
     * @param content 机器人插件上下文
     */
    public void command(RobotPluginContent content) {
        String msg = content.getContent();
        switch (msg) {
            case "#插件列表":
                this.addPluginsListMessage(content);
                break;
            case "#开机":
                if (ROOT_MANAGE_QQ.contains(content.getMessageEvent().getSender().getId())) {
                    start = true;
                    this.addRobotStatusMessage(content);
                }
                break;
            case "#关机":
                if (ROOT_MANAGE_QQ.contains(content.getMessageEvent().getSender().getId())) {
                    start = false;
                    this.addRobotStatusMessage(content);
                }
                break;
            case "#机器人状态":
                this.addRobotStatusMessage(content);
                break;
            case "#管理员列表":
                this.addManageMessage(content);
                break;
            case "#群白名单":
                if (ROOT_MANAGE_QQ.contains(content.getMessageEvent().getSender().getId())) {
                    this.addGroupListMessage(content);
                }
                break;
            case "#开启群管理员权限":
                if (ROOT_MANAGE_QQ.contains(content.getMessageEvent().getSender().getId())) {
                    GROUP_ADMIN_PERMISSION = true;
                    content.putReplyMessage("群管理员权限：true");
                }
                break;
            case "#关闭群管理员权限":
                if (ROOT_MANAGE_QQ.contains(content.getMessageEvent().getSender().getId())) {
                    GROUP_ADMIN_PERMISSION = false;
                    content.putReplyMessage("群管理员权限：false");
                }
                break;
            default:
                if (msg.startsWith("#开启插件")) {
                    this.startPlugin(content, msg.replace("#开启插件", "").trim(), true);
                    this.addPluginsListMessage(content);
                } else if (msg.startsWith("#关闭插件")) {
                    this.startPlugin(content, msg.replace("#关闭插件", "").trim(), false);
                    this.addPluginsListMessage(content);
                } else if (msg.startsWith("#插件详情")) {
                    String name = msg.replace("#插件详情", "").trim();
                    StringBuilder text = new StringBuilder();
                    if ("系统管理插件".equals(name)) {
                        text.append(String.format(template, this.info().getName(), true));
                        text.append(this.info().getDesc());
                    } else {
                        RobotPluginManage pluginManage = this.manages.get(content.getPluginQqKey());
                        RobotPlugin plugin = pluginManage.get(name);
                        if (plugin == null) {
                            text.append(String.format("无此插件【%s】", name));
                        } else {
                            text.append(String.format(template, plugin.info().getName(), pluginManage.isStart(name)));
                            text.append(plugin.info().getDesc());
                        }
                    }
                    content.putReplyMessage(new PlainText(text.toString()));
                } else if (ROOT_MANAGE_QQ.contains(content.getMessageEvent().getSender().getId())) {
                    // root管理员才有的功能
                    if (msg.startsWith("#添加管理员")) {
                        this.addManage(content, true);
                    } else if (msg.startsWith("#删除管理员")) {
                        this.addManage(content, false);
                    } else if (msg.startsWith("#添加群")) {
                        this.addGroupList(content, content.getContent().replaceFirst("#添加群", "").trim(), true);
                    } else if (msg.startsWith("#删除群")) {
                        this.addGroupList(content, content.getContent().replaceFirst("#删除群", "").trim(), false);
                    }
                }
                break;
        }
    }

    /**
     * 添加插件列表消息
     *
     * @param content 机器人插件上下文
     */
    private void addPluginsListMessage(RobotPluginContent content) {
        StringBuffer text = new StringBuffer();
        text.append(String.format(template, this.info().getName(), true));
        this.manages.get(content.getPluginQqKey()).getAllFlag().forEach((key, value) -> {
            text.append(String.format(template, key.info().getName(), value));
        });
        content.putReplyMessage(new PlainText(text.toString()));
    }

    /**
     * 添加机器人状态消息
     *
     * @param content 机器人插件上下文
     */
    private void addRobotStatusMessage(RobotPluginContent content) {
        content.putReplyMessage(String.format("机器人状态：%s", start));
    }

    /**
     * 添加管理员列表信息
     *
     * @param content 机器人插件上下文
     */
    private void addManageMessage(RobotPluginContent content) {
        StringBuilder message = new StringBuilder();
        message.append("root管理员列表：\n");
        ROOT_MANAGE_QQ.forEach(item -> {
            message.append(item).append("\n");
        });
        message.append("普通管理员列表：\n");
        NORMAL_MANAGE_QQ.forEach(item -> {
            message.append(item).append("\n");
        });
        content.putReplyMessage(message.toString());
    }

    /**
     * 添加管理员列表
     *
     * @param content 机器人插件上下文
     * @param add     是否添加
     */
    private void addManage(RobotPluginContent content, boolean add) {
        AtomicBoolean flag = new AtomicBoolean(true);
        content.getMessageEvent().getMessage().forEach(singleMessage -> {
            if (singleMessage instanceof At) {
                if (add) {
                    NORMAL_MANAGE_QQ.add(((At) singleMessage).getTarget());
                } else {
                    NORMAL_MANAGE_QQ.remove(((At) singleMessage).getTarget());
                }
                flag.set(false);
            }
        });
        if (flag.get()) {
            String qq;
            if (add) {
                qq = content.getContent().replaceFirst("#添加管理员", "").trim();
            } else {
                qq = content.getContent().replaceFirst("#删除管理员", "").trim();
            }
            if (StrUtil.isNotEmpty(qq)) {
                try {
                    if (add) {
                        NORMAL_MANAGE_QQ.add(Long.parseLong(qq));
                    } else {
                        NORMAL_MANAGE_QQ.remove(Long.parseLong(qq));
                    }
                } catch (Exception e) {
                    String error = StrUtil.format("转换qq失败[{}]", qq);
                    log.error(error, e);
                    content.putReplyMessage(error);
                }
            }
        }
        this.addManageMessage(content);
    }

    /**
     * 获取启动的插件列表
     *
     * @param content 机器人插件上下文
     * @return 插件列表
     */
    public List<RobotPlugin> getPlugin(RobotPluginContent content) {
        return this.manages.get(content.getPluginQqKey()).getStart();
    }

    /**
     * 根据插件名称启动插件
     *
     * @param content 机器人插件上下文
     * @param name    插件名称{@link RobotPlugin#info()}
     * @param start   是否启用
     */
    public void startPlugin(RobotPluginContent content, String name, boolean start) {
        this.manages.get(content.getPluginQqKey()).start(name, start);
    }

    /**
     * 初始化插件内容
     *
     * @param key 管理插件key
     */
    public void initPlugin(Long key) {
        if (!this.manages.containsKey(key)) {
            this.manages.put(key, SpringUtil.getBean(RobotPluginManage.class));
        }
    }

    /**
     * 添加群白名单列表消息
     *
     * @param content 机器人插件上下文
     */
    private void addGroupListMessage(RobotPluginContent content) {
        StringBuffer text = new StringBuffer("群白名单：");
        GROUP_WHITE_LIST.forEach(item -> {
            text.append("\n").append(item);
        });
        content.putReplyMessage(new PlainText(text.toString()));
    }

    /**
     * 添加群白名单列表
     *
     * @param content 机器人插件上下文
     * @param qq      添加的群号
     * @param add     是否添加
     */
    private void addGroupList(RobotPluginContent content, String qq, boolean add) {
        if (StrUtil.isNotEmpty(qq)) {
            try {
                if (add) {
                    GROUP_WHITE_LIST.add(Long.valueOf(qq));
                } else {
                    GROUP_WHITE_LIST.remove(Long.valueOf(qq));
                }
                this.addGroupListMessage(content);
            } catch (Exception e) {
                String error = StrUtil.format("转换qq失败[{}]", qq);
                log.error(error, e);
                content.putReplyMessage(error);
            }
        }
    }
}
